import * as Cesium from 'cesium';
// 拾取位置点
const getCatesian3FromPX = (viewer: Cesium.Viewer, px: Cesium.Cartesian2) => {
  if (!px) return;
  const picks = viewer.scene.drillPick(px);
  let cartesian = null;
  let isOn3dtiles = false,
    isOnTerrain = false;
  for (let i in picks) {
    let pick = picks[i];

    if (
      (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
      (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
      (pick && pick.primitive instanceof Cesium.Model)
    ) {
      //模型上拾取
      isOn3dtiles = true;
    }
    // 3dtilset
    if (isOn3dtiles) {
      viewer.scene.pick(px); // pick
      cartesian = viewer.scene.pickPosition(px);
      if (cartesian) {
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        if (cartographic.height < 0) cartographic.height = 0;
        let lon = Cesium.Math.toDegrees(cartographic.longitude),
          lat = Cesium.Math.toDegrees(cartographic.latitude),
          height = cartographic.height;
        cartesian = Cesium.Cartesian3.fromDegrees(lon, lat, height);
      }
    }
  }
  let boolTerrain = viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
  if (!isOn3dtiles && !boolTerrain) {
    var ray = viewer.scene.camera.getPickRay(px);
    if (!ray) return null;
    cartesian = viewer.scene.globe.pick(ray, viewer.scene);
    isOnTerrain = true;
  }
  // 地球
  if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
    cartesian = viewer.scene.camera.pickEllipsoid(px, viewer.scene.globe.ellipsoid);
  }
  if (cartesian) {
    return cartesian;
  }
  return false;
};

export enum DrawType {
  POINT = 0,
  POLYLINE = 1,
  POLYGON = 2,
}

export interface DrawOptions {
  type?: DrawType;
  finishCallback?: Function;
  drawingCallback?: Function;
  showShape?: boolean;
  clampToGround?: boolean;
}

export default function useDraw(viewer: Cesium.Viewer, options: DrawOptions) {
  const _positions: Cesium.Cartesian3[] = [];
  let _lcc = 0; // left click count
  let _handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  let _drawType: DrawType = options.type || DrawType.POINT;
  let _floatingEnitity: Cesium.Entity | undefined;
  const _pointEntities: Cesium.Entity[] = [];
  let _drawingCallback = options.drawingCallback || function () {};
  let _finishCallback = options.finishCallback || function () {};
  let _active = false;
  const _showShape = options.showShape || true;

  function leftClick(e: any) {
    const pos = getCatesian3FromPX(viewer, e.position);
    if (pos) {
      _positions.push(pos);
      _lcc++;
      if (_showShape) {
        const entity = viewer.entities.add({
          id: Cesium.createGuid(),
          position: pos,
          point: {
            color: Cesium.Color.RED,
            pixelSize: 10,
            outlineWidth: 2,
            outlineColor: Cesium.Color.fromCssColorString('#3dc8df'),
          },
        });
        _pointEntities.push(entity);
      }
      if (!_floatingEnitity && _showShape) {
        if (_drawType === DrawType.POLYLINE && !_floatingEnitity) {
          let entity = viewer.entities.add({
            id: Cesium.createGuid(),
            polyline: {
              positions: new Cesium.CallbackProperty(() => [..._positions], true),
              clampToGround: options.clampToGround || true,
              width: 1,
              material: Cesium.Color.RED,
            },
          });
          _floatingEnitity = entity;
        } else if (_drawType === DrawType.POLYGON && !_floatingEnitity) {
          let entity = viewer.entities.add({
            id: Cesium.createGuid(),
            polygon: {
              hierarchy: new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy([..._positions]), false),
              material: Cesium.Color.YELLOW.withAlpha(0.4),
              perPositionHeight: options.clampToGround || true,
            },
            polyline: {
              // 线段要闭合
              positions: new Cesium.CallbackProperty(() => [..._positions, _positions[0]], false),
              clampToGround: options.clampToGround || false,
              width: 1,
              material: Cesium.Color.RED,
            },
          });
          _floatingEnitity = entity;
        } else {
        }
      }
      dispatchDrawingCallback;
    }
  }

  function mouseMove(e: any) {
    const pos = getCatesian3FromPX(viewer, e.endPosition);
    if (pos) {
      if (_positions.length > _lcc) {
        _positions.pop();
      }
      _positions.push(pos);
      dispatchDrawingCallback();
    }
  }

  function rightClick(e: any) {
    const pos = getCatesian3FromPX(viewer, e.position);
    drawStop();
    dispatchDrawingCallback();
  }

  function bindEvt() {
    _handler.setInputAction(leftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    _handler.setInputAction(mouseMove, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    _handler.setInputAction(rightClick, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  const dispatchDrawingCallback = () => {
    const res = [..._positions];
    if (_lcc < res.length) {
      res.pop(); // 取出最后一个绘制的点
    }
    if (res.length <= 0) return;

    if (_active) {
      _drawingCallback(res);
    } else {
      _finishCallback(res);
    }
  };

  const drawStart = (drawType?: DrawType) => {
    _drawType = typeof drawType === 'undefined' ? _drawType : drawType;
    _active = true;
    setCursorStyle(true);
    bindEvt();
  };

  const drawStop = () => {
    _active = false;
    _handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    _handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    _handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    setCursorStyle(false);
  };

  const drawClear = () => {
    _positions.length = 0;
    _lcc = 0;
    if (_floatingEnitity) {
      viewer.entities.remove(_floatingEnitity);
      _floatingEnitity = undefined;
    }
    while (_pointEntities.length >= 1) {
      let e = _pointEntities.pop();
      if (e) viewer.entities.remove(e);
    }
  };

  const setCursorStyle = (flag: boolean) => {
    try {
      let map = document.getElementById('cesiumContainer');
      if (map) map.style.cursor = flag === true ? 'crosshair' : 'default';
    } catch {
      console.error('未匹配到地图元素！');
    }
  };

  return {
    drawStart,
    drawStop,
    drawClear,
  };
}
